package base.display.activity;

import java.lang.reflect.Field;
import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import base.display.model.BaseModel;
import base.display.model.IGetDataListener;
import base.utils.Logger;

public class BaseFragment<Request, Response, Model extends BaseModel<Request, Response>> extends Fragment implements IGetDataListener<Request, Response> {

	protected final String TAG = getClass().getSimpleName();

	protected BasePageDataHolder mPageData;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		mPageData = new BasePageDataHolder(savedInstanceState, getActivity(), BaseFragment.this) {

			@Override
			public void parseBundle(Bundle bundleToFetchData) {
				// TODO Auto-generated method stub
				BaseFragment.this.parseBundle(bundleToFetchData);
			}

			@Override
			public void packingBundle(Bundle bundleToPutData) {
				// TODO Auto-generated method stub
				BaseFragment.this.packingBundle(bundleToPutData);
			}
		};
	}

	protected void parseBundle(Bundle bundleToFetchData) {
		Logger.verbose(TAG, "parseBundle");

	}

	protected void packingBundle(Bundle bundleToPutData) {
		Logger.verbose(TAG, "packingBundle");
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		super.onSaveInstanceState(outState);
		mPageData.packingBundle(outState);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		return super.onCreateView(inflater, container, savedInstanceState);
	}

	@Override
	public void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		doInitiateModel();
	}

	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		onSynchronize();
	}

	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		onModelClear();
	}

	@Override
	public void onFinish(Request request, Response response) {
		// TODO Auto-generated method stub
		Logger.verbose(TAG, "onFinish");
	}

	@Override
	public void onError(Request request, Exception e) {
		// TODO Auto-generated method stub
		Logger.verbose(TAG, "onError");
	}

	@Override
	public void onProgress(Request request, int progress) {
		// TODO Auto-generated method stub
		Logger.verbose(TAG, "onProgress");
	}

	private ArrayList<Model> mModels = new ArrayList<Model>();

	private void doInitiateModel() {
		Logger.verbose(TAG, "doInitiateModel");
		onModelInitiate();
		doFindModels();
	}

	@SuppressWarnings({
		"unchecked"
	})
	protected void doFindModels() {
		Logger.verbose(TAG, "doFindModels");
		mModels.clear();
		ArrayList<Field> filedsA = new ArrayList<Field>();
		Class<?> cls = getClass();
		do {
			Field fields[] = cls.getDeclaredFields();
			for (Field f : fields) {
				filedsA.add(f);
			}
		} while ((cls = cls.getSuperclass()) != Activity.class);

		int length = filedsA.size();

		for (int i = 0; i < length; i++) {
			Field field = filedsA.get(i);
			field.setAccessible(true);
			try {
				Object fieldObj = field.get(this);
				if (fieldObj instanceof BaseModel) {
					Logger.verbose(TAG, "\t found -> " + field.getName());
					((Model) fieldObj).setGetDataListener(this);
					mModels.add((Model) fieldObj);
				}
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * Your models must initiate here
	 */
	protected void onModelInitiate() {
		Logger.verbose(TAG, "onModelInitiate");
	}

	protected void addModel(Model model) {
		if (mModels.contains(model)) {
			return;
		}
		mModels.add(model);
	}

	protected void onModelClear() {
		Logger.verbose(TAG, "onModelClear");
		for (Model data : mModels) {
			data.clear();
		}
	}

	protected void onSynchronize() {
		Logger.verbose(TAG, "onSynchronize");
	}

	/**
	 * Getting default model
	 * 
	 * @return
	 */
	protected Model getModel() {
		return null;
	}

}
